package dyyx.drools.test;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatelessKnowledgeSession;

import dyyx.Utils;


/**
 * drools  session  共享与非共享 正确性及性能对比测试
 * @author dugang
 *
 */

public class ConncTestMain {

	private static int threads = 5;

	private static final AtomicLong shareOkCount = new AtomicLong();
	private static final AtomicLong shareFailCount = new AtomicLong();
	private static final AtomicLong shareErrorCount = new AtomicLong();


	private static final AtomicLong noshareOkCount = new AtomicLong();
	private static final AtomicLong noshareFailCount = new AtomicLong();
	private static final AtomicLong noshareErrorCount = new AtomicLong();


	public static void main(String[] args) throws Exception {

		int threadsTmp = Utils.getSysPropInt("threads");
		if (threadsTmp > 0) {
			threads = threadsTmp;
		}

		String drl = Utils.readFromClassPath("drools/test.drl", null);

		long start = System.currentTimeMillis();
		KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
		kbuilder.add(ResourceFactory.newReaderResource(new StringReader(drl)), ResourceType.DRL);
		Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
		KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
		kbase.addKnowledgePackages(pkgs);
		long end = System.currentTimeMillis();
		long time = end - start;
		System.out.println("time=" + time);

		System.out.println("threads=" + threads);

		StatelessKnowledgeSession session = kbase.newStatelessKnowledgeSession();
		ScoreHandler scoreHandler = new ScoreHandler();
		session.setGlobal("score_handler", scoreHandler);

		List<RuleThread> threadList = new ArrayList<RuleThread>();

		// share 所有线程使用一个 session
		for (int i = 0; i < threads; i++) {
			RuleThread thread = new RuleThread(session, true);
			threadList.add(thread);
		}

		// noshare 一个线程一个session
		for (int i = 0; i < threads; i++) {
			session = kbase.newStatelessKnowledgeSession();
			session.setGlobal("score_handler", scoreHandler);
			RuleThread thread = new RuleThread(session, false);
			threadList.add(thread);
		}

		// start all threads
		// 打乱顺序  
		Collections.shuffle(threadList);
		for (RuleThread item : threadList) {
			item.start();
		}

		while (true) {
			Thread.sleep(2000);
			System.out.println(shareOkCount + "," + shareFailCount +","+shareErrorCount + "#" + noshareOkCount + ","+noshareFailCount+"," + noshareErrorCount);
		}

	}

	private static class RuleThread extends Thread {

		private StatelessKnowledgeSession session;
		private boolean share;

		private static final AtomicLong shareSeq = new AtomicLong();
		private static final AtomicLong noShareSeq = new AtomicLong();

		private final Random rand = new Random();

		public RuleThread(StatelessKnowledgeSession session, boolean share) {
			this.session = session;
			this.share = share;

			if (share) {
				String name = "share-" + shareSeq.getAndIncrement();
				setName(name);
			} else {
				String name = "noshare-" + noShareSeq.getAndIncrement();
				setName(name);
			}

		}

		public void run() {

			while (true) {

				try{
					runOne();
				}catch(Throwable e){
					
					if(share){
						shareErrorCount.getAndIncrement();
					}else{
						noshareErrorCount.getAndIncrement();
					}
				}
			}
		}

		
		private void runOne(){
			
			int score = rand.nextInt(100);
			String expectedGrade = ScoreHandler.getGrade(score);

			RuleContext context = new RuleContext();
			context.setScore(score);
			session.execute(context);

			if (share) {

				// 判断执行结果是否ok
				if (expectedGrade.equals(context.getGrade())) {
					shareOkCount.getAndIncrement();
				} else {
					shareFailCount.getAndIncrement();
				}

			} else {

				if (expectedGrade.equals(context.getGrade())) {
					noshareOkCount.getAndIncrement();
				} else {
					noshareFailCount.getAndIncrement();
				}

			}
		}
		
		public String toString() {
			return getName() + "," + share + "," + session;
		}
	}
}
